from game.error import GameError
from game.dispatcher import Dispatcher

import uuid
import time
import logging

logger = logging.getLogger(__name__)

class Room(Dispatcher):
    registered_room_types = {}
    @classmethod
    def register(cls, room_cls):
        if room_cls.type:
            cls.registered_room_types[room_cls.type] = room_cls

    @classmethod
    def create_room(cls, type_name, room_id):
        room_cls = cls.registered_room_types.get(type_name, None)
        if room_cls:
            room = room_cls()
            room.id = room_id
            cls.objects[room_id] = room
            return room
        else:
            raise GameError('Game is not supported')

    @classmethod
    def get(cls, id_):
        return cls.objects.get(id_, None)

    @classmethod
    def clean(cls):
        logger.debug('Room clean: current objects %d', len(cls.objects))
        t = time.time() - 30 * 60
        for id_, r in cls.objects.iteritems():
            if len(r.players) > 0:
                continue

            if r.last_access_time > t:
                continue

            logger.debug('%s:delete', r)
            cls.objects.pop(id_, None)

        logger.debug('Room cleaned: current objects %d', len(cls.objects))

    type = None
    max_players = 8

    objects = {}

    def __init__(self):
        self.players = {}
        self.last_access_time = 0

        self._refresh()

    def _refresh(self):
        self.last_access_time = time.time()

    def __repr__(self):
        return '<%s %s>' % (self.__class__.__name__, getattr(self, 'id', '?'))

    def player_leave(self, player):
        logger.debug('%s:player_leave %s', self, player)
        self.on_player_leave(player)
        self.players.pop(player.id, None)
        if len(self.players) == 0:
            self._refresh()

    def player_enter(self, player):
        logger.debug('%s:player_enter %s', self, player)
        self.players[player.id] = player
        self.on_player_enter(player)

    def player_message(self, player, action, message):
        logger.debug('%s:player_message %s: %s %s', self, player, action, message)
        return self.dispatch(action, player, message)

    def is_full(self):
        return len(self.players) >= self.max_players

    def on_player_leave(self, player):
        self.broadcast_to_others(player, 'player_leave_room', {
                    'player': player.name,
                     })

    def on_player_enter(self, player):
        self.broadcast_to_others(player, 'player_enter_room', {
                    'player': player.name,
                     })

    def broadcast(self, action, message):
        for p in self.players.itervalues():
            p.send(action, message)

    def broadcast_to_others(self, player, action, message):
        for p in self.players.itervalues():
            if player != p:
                p.send(action, message)

    def _handle_chat(self, player, message):
        self.broadcast('chat', {
                    'body': message['body'],
                    'from': {
                             'id': player.id,
                             'name': player.name,
                             }
                     })
